'''
Created on 2011-12-2

@author: Administrator
'''
import logging
from taskflow.taskflowtemplate import *
import functools
import task
import copy


def WarpperFun():
    return True


class Node():
    def __init__(self, name, templateid, condition, nodes):
        self.templateid = templateid
        self.taskid = None
        self.task_db_id = None
        self.name = name
        self.task_result = None
        self.task_status = None
        self.associated_nodes = nodes
        self.condition = condition
        self.status = WAITING_TRIIGGERING
        self.start_time = None
        self.end_time  = None
        self.result_message  = ''
        
        
    def OnTaskFinish(self, taskid, result):
        if self.taskid != taskid:
            raise ValueError('id not equle')
        
        self.status = FINISH
        self.task_result = result
        
    def OnNodeFinish(self, node):
        if node.name in self.associated_nodes:
            self.associated_nodes.remove(node.name)
            if self.condition() == True:
                self.status = TRIGGERED
                return
            if len(self.associated_nodes) == 0:
                self.status = NOT_TRIGGER
                self.task_status = task.NORUN
        
        
    def IsFinish(self):
        return self.status == FINISH or self.status == NOT_TRIGGER
        
    def Success(self):
        return self.task_result == task.SUCCESS
        
    def Failure(self):
        return self.task_result == task.FAILURE
    
    def Exception(self):
        return self.task_result == task.EXCEPTION
    
    def NoRun(self):
        return self.task_status == task.NORUN
    
    
class TaskFlow():
    def __init__(self, index, templateid, nodes, template):
        self.node_list = {}
        self.cond_run_env= {}
        self.index = index
        self.templateid = templateid
        self.template = template
        self.AddNodes(nodes)
        self.task_list = {}
        self.status = task.IDLE
        self.begin_run_time = None
        self.end_time = None
        self.result = None
        self.result_message = None
        self.addtional_mail_receiver = ''
        self.is_task_flow = True
        self.trigger_node = None
        self.dbid = None

    
    def AddNodes(self, node_list):
        for v in node_list:
            self.AddNode(v)
            
    
    def OnTaskFinish(self, taskid, result, dbid, start_time, end_time, result_message):
        if taskid not in self.task_list:
            raise ValueError('id not exits taskflow')
        
        node = self.task_list[taskid]
        node.task_db_id  = dbid
        node.start_time = start_time
        node.end_time = end_time
        node.task_result  = result
        node.result_message = result_message
        node.OnTaskFinish(taskid, result)
        self.task_list.pop(taskid)
        self.OnNodeFinish(node)
        
                
    def CreateTaskFail(self, node_name):
        if node_name not in self.node_list:
            raise ValueError('node name not exits taskflow')
        
        node  = self.node_list[node_name]
        node.status = FINISH
        self.task_status = task.NORUN
        
        self.OnNodeFinish(node)
        
    
    def OnNodeFinish(self, node):
        for v in self.node_list.values():
            if v.status != WAITING_TRIIGGERING:
                continue
            v.OnNodeFinish(node)
            if v.IsFinish() == True:
                self.OnNodeFinish(v)
                
    def IsFinish(self):
        for v in self.node_list.values():
            if v.IsFinish() == False :
                return False
        self.result = task.SUCCESS
        return True  
        
        
    def AddNode(self, nodeinfo):
        if nodeinfo.judge_code != None: 
            condition_func = functools.partial(eval, nodeinfo.judge_code, self.cond_run_env)
        else:
            condition_func = WarpperFun
        
        n = Node(nodeinfo.name, nodeinfo.tasktemplateid, condition_func,  nodeinfo.associated_nodes.copy())
        self.node_list[n.name] = n
        self.cond_run_env[n.name] = n
    
    
    def GetFirstTriggerNode(self):
        node_list  = []
        for v in self.node_list.values():
            if len(v.associated_nodes) == 0:
                v.status = BEGUN
                node_list.append(v)
        print [v.name for v in node_list]
        return node_list
    
    def GetNode(self, name):
        return self.node_list[name]
    
    
    def SetTaskID(self, node_name, taskid):
        if node_name not in self.node_list:
            raise ValueError('aleady has same name node')
        
        node  = self.node_list[node_name]
        node.taskid = taskid
        self.task_list[taskid] = node
        
    def GetTriggerNode(self):
        nodes = [v for v in self.node_list.itervalues() if v.status == TRIGGERED]
        for v in nodes:
            v.status = BEGUN
        return nodes
